using System;

namespace Microsoft.Isam.Esent.Serialization
{
	/// <summary>This enum defines what operation caused the <see cref="iNotifyTableChanged.TableChanged" /> event.</summary>
	/// <seealso cref="iNotifyTableChanged" />
	public enum NotifyTableChangedAction
	{
		/// <summary>An item was added to the collection.</summary>
		Add,
		/// <summary>An item was removed from the collection.</summary>
		Remove,

		/// <summary>One of more fields of the item were updated.</summary>
		Update,

		/// <summary>The content of the collection changed dramatically,
		/// as the result of
		/// <see cref="iSerializerSession.ImportTable">table</see>
		/// <see cref="iSerializerSession.ImportTables">import</see>,
		/// or <see cref="Cursor{tRow}.AddRange">Cursor.AddRange</see>.</summary>
		Reset
	}

	/// <summary>The argument for the <see cref="iNotifyTableChanged.TableChanged" /> event.</summary>
	/// <seealso cref="iNotifyTableChanged" />
	public struct NotifyTableChangedArgs
	{
		/// <summary>The action that caused the event.</summary>
		public readonly NotifyTableChangedAction Action;

		/// <summary>Bookmark of the affected record. May be null.</summary>
		public readonly ByteArray Bookmark;

		/// <summary>Updated column.
		/// May be null, which indicates several columns were updated.</summary>
		public readonly string Column;

		/// <summary></summary>
		public NotifyTableChangedArgs( NotifyTableChangedAction action )
		{
			this.Action = action;
			this.Bookmark = ByteArray.Empty;
			this.Column = null;
		}

		/// <summary></summary>
		public NotifyTableChangedArgs( NotifyTableChangedAction action, ByteArray bookmark )
		{
			this.Action = action;
			this.Bookmark = bookmark;
			this.Column = null;
		}

		/// <summary></summary>
		public NotifyTableChangedArgs( NotifyTableChangedAction action, ByteArray bookmark, string field )
		{
			this.Action = action;
			this.Bookmark = bookmark;
			this.Column = field;
		}
	}

	/// <summary></summary>
	/// <seealso cref="iNotifyTableChanged" />
	public delegate void NotifyTableChangedHandler( Object sender, NotifyTableChangedArgs e );

	/// <summary>This interface allows a client to receive notifications when the table is changed.</summary>
	/// <remarks><para>This interface is implemented by EseCursorBase class.</para>
	/// <para><b>NB:</b> if you're using ESE in highly concurrent environment (e.g. network server like the AD),
	/// and you've called EseTableAttribute.setEventsDispatcher, then events might ruin the parallelism.<br />
	/// If your situation is that tight, just ignore this interface, and implement your own notifications mechanism.
	/// Unless you've called
	/// <see cref="Attributes.EseTableAttribute"/>.<see cref="Attributes.EseTableAttribute.setEventsDispatcher">setEventsDispatcher</see>, 
	/// events are not dispatched across threads.</para></remarks>
	// TODO: use weak event instead, see http://www.codeproject.com/KB/cs/WeakEvents.aspx</remarks>
	public interface iNotifyTableChanged
	{
		/// <summary>This event occurs after the table has been changed.</summary>
		event NotifyTableChangedHandler TableChanged;
	}
}